package com.hyts.rpclet.config;

import com.hyts.rpclet.bean.RpcletProperties;
import com.hyts.rpclet.constant.RpcletConst;
import com.hyts.rpclet.handler.RpcletServerHandler;
import com.hyts.rpclet.listener.RpcletEventListener;
import com.hyts.rpclet.util.SpringContextUtils;
import org.eclipse.jetty.http2.server.HTTP2CServerConnectionFactory;
import org.eclipse.jetty.server.*;
import org.eclipse.jetty.server.handler.HandlerList;
import org.eclipse.jetty.util.ArrayUtil;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.eclipse.jetty.util.thread.ThreadPool;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.web.embedded.jetty.JettyServerCustomizer;
import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;


/**
 * project-name:coffice-toolbox
 * package-name:com.hyts.rpclet.server
 * author:Libo/Alex
 * create-date:2019-07-09 21:51
 * copyright:libo-hyts-github
 * email:libo2dev@aliyun.com
 * description:此类主要用于:
 */
@Configuration
public class RpcletServerConfiguration implements WebServerFactoryCustomizer<JettyServletWebServerFactory> {


    @Autowired
    SpringContextUtils springContextUtils;


    @Autowired
    RpcletProperties rpcletProperties;


    @Autowired
    ServerProperties serverProperties;

    /**
     * 定制化配置jetty服务handler
     * @param factory
     */
    @Override
    public void customize(JettyServletWebServerFactory factory) {
        factory.setThreadPool(settingThreadPool(factory));
        factory.addServerCustomizers((JettyServerCustomizer) server -> {
            settingHttp2Connector(server);
            settingRpcletServerHandler(server);
        });
    }

    /**
     * 设置 ThreadPool
     * @param factory
     * @return
     */
    private ThreadPool settingThreadPool(JettyServletWebServerFactory factory){
        QueuedThreadPool queuedThreadPool = new QueuedThreadPool();
        queuedThreadPool.setIdleTimeout(rpcletProperties.getIdleTimeout());
        queuedThreadPool.setDetailedDump(true);
        queuedThreadPool.setMaxThreads(rpcletProperties.getMaxThreadsNum());
        queuedThreadPool.setMinThreads(rpcletProperties.getMinThreadsNum());
        queuedThreadPool.setName(RpcletConst.DEFAULT_THREAD_POOL_NAME);
        factory.setThreadPool(queuedThreadPool);
        return queuedThreadPool;
    }

    /**
     * 设置 http2Connector连接器
     * @param server
     */
    private void settingHttp2Connector(Server server){
        // Http服务总体配置功能
        HttpConfiguration config = new HttpConfiguration();
        // HTTP/1.1 support.
        HttpConnectionFactory http1 = new HttpConnectionFactory(config);
        // HTTP/2 cleartext support.
        HTTP2CServerConnectionFactory http2c = new HTTP2CServerConnectionFactory(config);
        int acceptors = -1;
        if (serverProperties.getJetty().getAcceptors() != null) {
            acceptors = serverProperties.getJetty().getAcceptors();
        }
        int selectors = -1;
        if (serverProperties.getJetty().getSelectors() != null) {
            selectors = serverProperties.getJetty().getSelectors();
        }
        ServerConnector connector = new ServerConnector(server, null, null, null, acceptors, selectors, http1,
                http2c);
        connector.setPort(rpcletProperties.getPort());
        server.setConnectors(new Connector[] { connector });
    }

    /**
     * 设置 rpcletserverhandler服务处理器
     * @param server
     */
    private void settingRpcletServerHandler(Server server){
        ApplicationContext applicationContext = SpringContextUtils.getApplicationContext();
        Handler[] handlers = server.getHandlers();
        HandlerList handlerList = new HandlerList();
        //handlerList.addEventListener(new RpcletEventListener());
        RpcletServerHandler rpcletServerHandler = new RpcletServerHandler();
        handlerList.setHandlers(ArrayUtil.prependToArray(rpcletServerHandler,handlers,Handler.class));
    }
}
